home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / ftpsubr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-15  |  6.2 KB  |  307 lines

  1. /* Routines common to both the FTP client and server
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  /* Mods by G1EMM */
  5.  /* Mods by KO4KS */
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "socket.h"
  10. #include "proc.h"
  11. #include "ftp.h"
  12. #include "ftpcli.h"
  13. #include "usock.h"
  14. #ifdef LZW
  15. #include "lzw.h"
  16. #endif
  17. #include "md5.h"
  18.  
  19.  
  20. #define    MD5BLOCK    64    /* Preferred MD5 block size */
  21.  
  22. void
  23. hashit (hash, total, hmark)
  24. int hash;
  25. long total, *hmark;
  26. {
  27.     while(hash && total >= (*hmark)+1000)    {
  28.         if (hash == V_HASH)
  29.             tputc('#');
  30.         if(hash == V_BYTE)
  31.             tprintf("Bytes sent : %ld\r", total);
  32.         *hmark += 1000;
  33.     }
  34.  
  35. }
  36.  
  37.  
  38. /* Send a file (opened by caller) on a network socket.
  39.  * Normal return: count of bytes sent
  40.  * Error return: -1
  41.  * re-written by KO4KS to (1) reduce code size (2) all binary compression
  42.  */
  43. long
  44. sendfile(fp,s,mode,hash)
  45. register FILE *fp;    /* File to be sent */
  46. register int s;        /* Socket to be sent on */
  47. int mode;    /* Transfer mode */
  48. int hash;    /* Print hash marks every BLKSIZE bytes */
  49. {
  50. register int c;
  51. register long total = 0;
  52. long hmark = 0;
  53. int oldf;
  54. struct usock *up;
  55. register struct mbuf *bp;
  56.  
  57.     if (mode == ASCII_TYPE)        {
  58.         oldf = setflush(s,-1);
  59.         /* Let the newline mapping code in usputc() do the work */
  60.         sockmode(s,SOCK_ASCII);
  61.     } else    
  62.         sockmode(s,SOCK_BINARY);
  63.     up = itop(s);
  64.     if (mode != ASCII_TYPE && up->zout == NULLLZW)    {    /* also, not lzw compressed */
  65.         for(;;){
  66.             pwait (0);    /* be a good neighbor and share! */
  67.             bp = ambufw(BLKSIZE);
  68.             if((bp->cnt = fread(bp->data,1,BLKSIZE,fp)) == 0){
  69.                 free_p(bp);
  70.                 break;
  71.             }
  72.             pwait (0);    /* be a good neighbor and share! */
  73.             total += bp->cnt;
  74.             if(send_mbuf(s,bp,0,NULLCHAR,0) == -1){
  75.                 total = -1;
  76.                 break;
  77.             }
  78.             hashit (hash, total, &hmark);
  79.         }
  80.     } else    {
  81.  
  82.             /* At this point, it is either ASCII_TYPE, or LZW compressed */
  83.         while((c = getc(fp)) != EOF)    {
  84.             if (mode == ASCII_TYPE)        {
  85. #ifndef TNOS_68K
  86. #if !defined(UNIX) && !defined(__TURBOC__)
  87.                 if(c == '\r'){
  88.                     /* Needed only if the OS uses a CR/LF
  89.                      * convention and getc doesn't do
  90.                      * an automatic translation
  91.                      */
  92.                     continue;
  93.                 }
  94. #endif
  95. #else
  96.                 if(c == '\l')
  97.                     continue;
  98. #endif
  99.                 if (!c)
  100.                     continue;
  101.             }
  102.             if(usputc(s,(char)c) == -1){
  103.                 total = -1;
  104.                 break;
  105.             }
  106.             total++;
  107.             hashit (hash, total, &hmark);
  108.             if (!(total % 256))
  109.                 pwait (0);    /* be a good neighbor and share! */
  110.         }
  111.     }
  112.     if (mode == ASCII_TYPE)    {
  113.         usflush(s);
  114.         setflush(s,oldf);
  115.     }
  116.     if(hash)
  117.         tputc('\n');
  118.     return total;
  119. }
  120. /* Receive a file (opened by caller) from a network socket.
  121.  * Normal return: count of bytes received
  122.  * Error return: -1
  123.  * re-written by KO4KS to (1) reduce code size (2) all binary compression
  124.  */
  125. long
  126. recvfile(fp,s,mode,hash)
  127. register FILE *fp;
  128. register int s;
  129. int mode;
  130. int hash;
  131. {
  132. register int c;
  133. register long total = 0;
  134. long hmark = 0;
  135. int cnt;
  136. struct usock *up;
  137. struct mbuf *bp;
  138.  
  139.     if (mode == ASCII_TYPE)
  140.         sockmode(s,SOCK_ASCII);
  141.     else
  142.         sockmode(s,SOCK_BINARY);
  143.     up = itop(s);
  144.     if (mode != ASCII_TYPE && up->zout == NULLLZW)    {    /* also, not lzw compressed */
  145.         while((cnt = recv_mbuf(s,&bp,0,NULLCHAR,0)) != 0){
  146.             pwait (0);    /* be a good neighbor and share! */
  147.             if(cnt == -1){
  148.                 total = -1;
  149.                 break;
  150.             }
  151.             total += cnt;
  152.             hashit (hash, total, &hmark);
  153.             pwait (0);    /* be a good neighbor and share! */
  154.             if(fp != NULLFILE){
  155.                 if(write_p(fp,bp) == -1){
  156.                     free_p(bp);
  157.                     total = -1;
  158.                     break;
  159.                 }
  160.                 free_p(bp);
  161.             } else
  162.                 send_mbuf(Curproc->output, bp, 0, NULLCHAR, 0);
  163.             pwait (0);    /* be a good neighbor and share! */
  164.         }
  165.     } else    {
  166.         while((c = recvchar(s)) != EOF){
  167.             if(fp != NULLFILE){
  168. #if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA)
  169.                 if (mode == ASCII_TYPE)        {
  170.                     if(c == '\n'){
  171.                         /* Needed only if the OS uses a CR/LF
  172.                          * convention and putc doesn't do
  173.                          * an automatic translation
  174.                          */
  175.                         putc('\r',fp);
  176.                     }
  177.                 }
  178. #endif
  179.                 if(putc(c,fp) == EOF){
  180.                     total = -1;
  181.                     break;
  182.                 }
  183.             } else
  184.                 tputc((char)c);
  185.             total++;
  186.             hashit (hash, total, &hmark);
  187.             if (!(total % 256))
  188.                 pwait (0);    /* be a good neighbor and share! */
  189.         }
  190.     }
  191.     /* Detect an abnormal close */
  192.     if(socklen(s,0) == -1)
  193.         total = -1;
  194.     if(hash)
  195.         tputc('\n');
  196.     return total;
  197. }
  198. /* Determine if a file appears to be binary (i.e., non-text).
  199.  * Return 1 if binary, 0 if ascii text after rewinding the file pointer.
  200.  *
  201.  * Used by FTP to warn users when transferring a binary file in text mode.
  202.  */
  203. int
  204. isbinary(fp)
  205. FILE *fp;
  206. {
  207.     int c,i;
  208.     int rval;
  209.  
  210.     rval = 0;
  211.     for(i=0;i<512;i++){
  212.         if((c = getc(fp)) == EOF)
  213.             break;
  214.         if(c & 0x80){
  215.             /* High bit is set, probably not text */
  216.             rval = 1;
  217.             break;
  218.         }
  219.     }
  220.     /* Assume it was at beginning */
  221.     fseek(fp,0L,SEEK_SET);
  222.     return rval;
  223. }
  224.  
  225. unsigned long
  226. getsize(fp)
  227. FILE *fp;
  228. {
  229.     fseek(fp,0L,SEEK_END);    /* Go to end of file */
  230.     return (unsigned long) ftell(fp);    /* Return file pointer position */
  231. }
  232.  
  233. /* Compute checksum of the first n bytes */
  234. unsigned long
  235. checksum(fp,n)
  236. FILE *fp;
  237. long n;
  238. {
  239.     unsigned long sum;
  240.     long i;
  241.     int c;
  242.  
  243.     rewind(fp);
  244.     sum = 0;
  245.     for(i=1;i<=n;i++){
  246.         if((c = fgetc(fp)) == EOF)
  247.             break;
  248.         sum += (unsigned long)c;
  249.     }
  250.     return sum;
  251. }
  252.  
  253. /* Compute MD5 hash of local file */
  254. int
  255. md5hash(fp,hash,ascii)
  256. FILE *fp;
  257. char hash[16];
  258. int ascii;
  259. {
  260.     MD5_CTX md;
  261.     char *buf;
  262.     int len;
  263.  
  264.     MD5Init(&md);
  265.  
  266.     if(ascii){
  267.         /* Text file, hash canonical form (newlines = crlf) */
  268.         char *cp;
  269.         int c;
  270.  
  271.         cp = buf = malloc(MD5BLOCK);
  272.         len = 0;
  273.         while((c = fgetc(fp)) != EOF){
  274.             if(c == '\n'){
  275.                 *cp++ = '\r';
  276.                 if(++len == MD5BLOCK){
  277.                     MD5Update(&md,buf,len);
  278.                     pwait(NULL);
  279.                     cp = buf;
  280.                     len = 0;
  281.                 }
  282.             }
  283.             *cp++ = c;
  284.             if(++len == MD5BLOCK){
  285.                 MD5Update(&md,buf,len);
  286.                 pwait(NULL);
  287.                 cp = buf;
  288.                 len = 0;
  289.             }
  290.         }
  291.         if(len != 0)
  292.             MD5Update(&md,buf,len);
  293.         free(buf);
  294.     } else {
  295.         buf = malloc(BUFSIZ);
  296.         while((len = fread(buf,1,BUFSIZ,fp)) != 0){
  297.             MD5Update(&md,buf,len);
  298.             pwait(NULL);
  299.         }
  300.         free(buf);
  301.     }
  302.     MD5Final(&md);
  303.     memcpy(hash,md.digest,16);
  304.     return 0;
  305. }
  306.  
  307.